﻿using ShenGu.Script;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Collections;
using System.IO;

namespace ScriptTest
{
    public partial class ScriptTestForm : Form
    {
        private IExecutor executor;

        public ScriptTestForm(IExecutor executor)
        {
            InitializeComponent();
            string script = executor.ScriptContent;
            if (!string.IsNullOrEmpty(script)) this.txtContent.Text = script;
            this.executor = executor;
        }

        private void btnParse_Click(object sender, EventArgs e)
        {
            try
            {
                ScriptParser parser = ScriptParser.Parse(txtContent.Text);
            }
            catch(Exception ex)
            {
                MessageBox.Show(GetInnerMessage(ex));
            }
        }

        private void btnExecute_Click(object sender, EventArgs e)
        {
            try
            {
                //解析javascript脚本，生成ScriptParser对象，语法树缓存在ScriptParser对象中
                //（ScriptParser对象支持并发，所以，对于同一段javascript脚本，可以将ScriptParser缓存）
                ScriptParser parser = ScriptParser.Parse(txtContent.Text);

                //创建脚本执行的上下文环境：ScriptContext
                ScriptContext context = new ScriptContext();

                //注册相应的类型到上下文环境中
                Type[] scriptTypes = executor != null ? executor.ScriptTypes : null;
                if (scriptTypes != null) context.RegisterTypes(scriptTypes);

                //通过AddMappings的方式，添加变量
                context.AddMappings(this);
                if (executor != null) context.AddMappings(executor);

                //直接添加变量
                Dictionary<string, object> scriptValues = executor != null ? executor.ScriptValues : null;
                if (scriptValues != null)
                {
                    foreach (KeyValuePair<string, object> kv in scriptValues)
                        context.AddValue(kv.Key, kv.Value);
                }

                //执行语法
                parser.Execute(context);

                //context.Result，可以取得return XXX;的结果
                txtResult.Text = context.ScriptResult.ToString();
            }
            catch (Exception ex)
            {
                MessageBox.Show(GetInnerMessage(ex));
            }
        }

        private string GetInnerMessage(Exception ex)
        {
            Exception innerEx = ex;
            while (innerEx.InnerException != null)
                innerEx = innerEx.InnerException;
            ScriptParseException scriptEx = innerEx as ScriptParseException;
            if (scriptEx != null)
                return string.Format("在行“{0}”列“{1}”出现语法错误：{2}", scriptEx.LineIndex, scriptEx.ColumnIndex, scriptEx.Message);
            return innerEx.Message;
        }

        [ScriptMapping("alert")]
        public void Alert(string message)
        {
            MessageBox.Show(message);
        }
    }

    public interface IExecutor
    {
        string ScriptContent { get; }

        Type[] ScriptTypes { get; }

        Dictionary<string, object> ScriptValues { get; }
    }
}
